package cn.jetpiece.cloud.resource.app.modular.scan.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.builder.CompareToBuilder;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.jetpiece.cloud.core.page.PageFactory;
import cn.jetpiece.cloud.resource.api.mode.query.ResourceQuery;
import cn.jetpiece.cloud.resource.api.mode.result.ResourceResult;
import cn.jetpiece.cloud.resource.app.modular.scan.wrapper.ResourceWrapper;
import cn.jetpiece.cloud.model.page.PageResult;
import cn.jetpiece.cloud.resource.annotation.model.RegisterResourceParam;
import cn.jetpiece.cloud.resource.annotation.model.ResourceParam;
import cn.jetpiece.cloud.resource.app.modular.scan.cache.ResourceCache;
import cn.jetpiece.cloud.resource.app.modular.scan.entity.Resource;
import cn.jetpiece.cloud.resource.app.modular.scan.mapper.ResourceMapper;
import cn.jetpiece.cloud.resource.app.modular.scan.service.ResourceService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * 资源表 服务实现类
 * </p>
 *
 * @author XuJZ
 * @since 2020-01-09
 */
@Slf4j
@Service
public class ResourceServiceImpl extends ServiceImpl<ResourceMapper, Resource> implements ResourceService {

    @Autowired
    private ResourceCache resourceCache;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void registerResource(RegisterResourceParam param) {
        Map<String, ResourceParam> resourceParamMap = param.getResourceParams();

        LambdaQueryWrapper<Resource> wrapper = new LambdaQueryWrapper<Resource>().eq(Resource::getAppCode, param.getAppCode());
        List<Resource> originals = list(wrapper);
        Map<String, Resource> originalMap = new HashMap<>();
        for (Resource original : originals) {
            originalMap.put(original.getCode(), original);
        }

        List<String> unionCodes = (List<String>) CollUtil.intersection(resourceParamMap.keySet(), originalMap.keySet());
        Set<String> unionCodeSet = new HashSet<>(unionCodes);

        //已经移除数据
        List<String> removeList = new ArrayList<>(originalMap.keySet());
        removeList.removeAll(unionCodeSet);
        if (removeList.size() > 0) {
            LambdaQueryWrapper<Resource> removeWrapper = new LambdaQueryWrapper<Resource>().eq(Resource::getAppCode, param.getAppCode()).in(Resource::getCode, removeList);
            List<Resource> resourceList = list(removeWrapper);
            /* 删除缓存数据 */
            resourceCache.removeCacheResource(resourceList);
            remove(removeWrapper);
        }

        //新增数据
        List<String> saveIdList = new ArrayList<>(resourceParamMap.keySet());
        saveIdList.removeAll(unionCodeSet);
        List<Resource> saveList = new ArrayList<>();
        for (String id : saveIdList) {
            ResourceParam source = resourceParamMap.get(id);
            Resource entity = new Resource();
            BeanUtil.copyProperties(source, entity);
            save(entity);
            saveList.add(entity);
        }

        //更新数据
        List<Resource> updateList = new ArrayList<>();
        for (String code : unionCodes) {
            Resource resource = originalMap.get(code);
            ResourceParam originalParam = new ResourceParam();
            BeanUtil.copyProperties(resource, originalParam);
            ResourceParam resourceParam = resourceParamMap.get(code);

            int compare = CompareToBuilder.reflectionCompare(originalParam, resourceParam);
            if (compare != 0) {
                log.debug("\n相差值:" + compare + "\n" + resourceParam);
                BeanUtil.copyProperties(resourceParam, resource);
                updateList.add(resource);
            }
        }
        if (updateList.size() > 0) {
            updateBatchById(updateList, updateList.size());
        }
        /* 只更新变化数据 */
        /*resourceCache.cacheResource(saveList);
        resourceCache.cacheResource(updateList);*/

        /* 全量更新 */
        List<Resource> resources = super.lambdaQuery().eq(Resource::getAppCode,param.getAppCode()).list();
        resourceCache.cacheResource(resources);
    }

    @Override
    public PageResult<ResourceResult> page(ResourceQuery query) {
        LambdaQueryWrapper<Resource> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotEmpty(query.getAppCode())) {
            wrapper.like(Resource::getAppCode, query.getAppCode());
        }
        if (StrUtil.isNotEmpty(query.getModularName())) {
            wrapper.like(Resource::getModularName, query.getModularName());
        }
        if (StrUtil.isNotEmpty(query.getName())) {
            wrapper.like(Resource::getName, query.getName());
        }
        if (StrUtil.isNotEmpty(query.getUrlPath())) {
            wrapper.like(Resource::getUrl, query.getUrlPath().replaceAll("!", "/"));
        }
        wrapper.eq(ObjectUtil.isNotEmpty(query.getInternal()),Resource::getInternal,query.getInternal());
        Page<Resource> page = page(PageFactory.defaultPage(), wrapper);
        return new ResourceWrapper(page).setWrapper(query.getWrapper()).wrapPageResult();
    }

}
